﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Microsoft.Xna.Framework;

using Radar;
using Radar.Navigation;

namespace Radar.TestUI
{
    public partial class NavMeshForm : Form
    {
        public NavMeshForm()
        {
            InitializeComponent();
        }

        Map map = null;

        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                map = MapFactory.Instance.CreateMap(MapDefinition.LoadFromFile(openFileDialog1.FileName));
                _getStartPos = true;
                _getEndPos = false;
                this.Refresh();
            }
        }

        NavZone selectedZone = null;

        float weightX;
        float weightY;

        private void DrawNavMeshForm_Paint(object sender, PaintEventArgs e)
        {
            if (map != null)
            {
                weightX = (float)e.Graphics.VisibleClipBounds.Width / map.Width;
                weightY = (e.Graphics.VisibleClipBounds.Height - 30f) / map.Height;
                foreach (NavZone zone in map.NavMesh.Zones)
                {
                    if (zone == selectedZone)
                    {
                        e.Graphics.FillRectangle(Brushes.Brown, new System.Drawing.RectangleF((zone.Left * weightX), (zone.Top * weightY + 30), (zone.GetWidth() * weightX), (zone.GetHeight() * weightY)));
                    }
                    else
                    {
                        e.Graphics.FillRectangle(Brushes.RosyBrown, new System.Drawing.RectangleF((zone.Left * weightX), (zone.Top * weightY + 30), (zone.GetWidth() * weightX), (zone.GetHeight() * weightY)));
                    }
                    foreach (Link link in zone.Links)
                    {
                        e.Graphics.DrawLine(Pens.SaddleBrown, new System.Drawing.PointF(link.CornerA.Point.X * weightX, link.CornerA.Point.Y * weightY + 30), new System.Drawing.PointF(link.CornerB.Point.X * weightX, link.CornerB.Point.Y * weightY + 30));
                    }
                }
                foreach (NavZone zone in map.NavMesh.Zones)
                {
                    foreach (Link link in zone.Links)
                    {
                        if (zone == selectedZone)
                        {
                            foreach (var wp in link.CornerA.Neighbours)
                            {
                                e.Graphics.DrawLine(Pens.Silver, new System.Drawing.PointF(link.CornerA.Point.X * weightX, link.CornerA.Point.Y * weightY + 30),
                                    new System.Drawing.PointF(wp.Point.X * weightX, wp.Point.Y * weightY + 30));
                            }
                            foreach (var wp in link.CornerB.Neighbours)
                            {
                                e.Graphics.DrawLine(Pens.Silver, new System.Drawing.PointF(link.CornerB.Point.X * weightX, link.CornerB.Point.Y * weightY + 30),
                                    new System.Drawing.PointF(wp.Point.X * weightX, wp.Point.Y * weightY + 30));
                            }

                            e.Graphics.DrawEllipse(Pens.DarkGreen, new RectangleF(link.CornerA.Point.X * weightX - 3, link.CornerA.Point.Y * weightY + 30 - 3, 6, 6));
                            e.Graphics.DrawEllipse(Pens.DarkGreen, new RectangleF(link.CornerB.Point.X * weightX - 3, link.CornerB.Point.Y * weightY + 30 - 3, 6, 6));
                        }
                    }
                }
                if (path != null)
                {
                    e.Graphics.DrawLines(Pens.DarkBlue, (from waypoint in path select new PointF(waypoint.Point.X * weightX, waypoint.Point.Y * weightY + 30)).ToArray());
                }
            }
        }

        private void DrawNavMeshForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (weightX > 0 && weightY > 0)
            {
                NavZone hoverZone = map.NavMesh.GetZoneAt(new Microsoft.Xna.Framework.Point((int)(e.X / weightX), (int)((e.Y - 30) / weightY)));
                if (hoverZone != selectedZone)
                {
                    selectedZone = hoverZone;
                    this.Refresh();
                }
            }
        }

        private bool _getStartPos = true;
        private bool _getEndPos = false;
        Microsoft.Xna.Framework.Point startPos;
        Microsoft.Xna.Framework.Point endPos;

        private Waypoint[] path = null;

        private void NavMeshForm_MouseUp(object sender, MouseEventArgs e)
        {
            if (weightX > 0 && weightY > 0)
            {
                if (_getStartPos)
                {
                    startPos = new Microsoft.Xna.Framework.Point((int)(e.X / weightX), (int)((e.Y - 30) / weightY));
                    _getStartPos = false;
                    _getEndPos = true;
                }
                else if (_getEndPos)
                {
                    endPos = new Microsoft.Xna.Framework.Point((int)(e.X / weightX), (int)((e.Y - 30) / weightY));
                    _getEndPos = false;
                    DateTime start = DateTime.Now;
                    for (int i = 0; i < 5000; i++)
                    {
                        var searcher = map.NavMesh.GetPathSearcher(startPos, endPos);
                        var result = Radar.PathFinding.SearchResult.NotFinished;
                        while (result == PathFinding.SearchResult.NotFinished)
                        {
                            result = searcher.SearchPath(10);
                        }
                        if (result == PathFinding.SearchResult.NoPathAvailable)
                        {
                            MessageBox.Show("No path could be found.");
                            break;
                        }
                        else
                        {
                            path = searcher.GetResultPath();
                        }
                    }
                    DateTime end = DateTime.Now;

                    MessageBox.Show(String.Format("{0:0} µs", (end - start).Milliseconds / 5f));

                    this.Refresh();

                    _getStartPos = true;
                }
            }
        }

    }
}
